package com.aptana.scope.parsing;

import beaver.Parser;
import beaver.ParsingTables;
import beaver.Scanner;
import beaver.Symbol;

import com.aptana.core.logging.IdeLog;
import com.aptana.scope.DescendantSelector;
import com.aptana.scope.GroupSelector;
import com.aptana.scope.ISelectorNode;
import com.aptana.scope.IntersectionSelector;
import com.aptana.scope.NameSelector;
import com.aptana.scope.NegativeLookaheadSelector;
import com.aptana.scope.OrSelector;
import com.aptana.scripting.ScriptingActivator;

/**
 * This class is a LALR parser generated by <a href="http://beaver.sourceforge.net">Beaver</a> v0.9.6.1 from the grammar
 * specification "Scope.grammar".
 */
@SuppressWarnings({ "nls" })
public class ScopeParser extends Parser
{

	static final ParsingTables PARSING_TABLES = new ParsingTables(
			"U9nja6rFma0GXETwBRQ25jIIa90OGeWHHOpwoL$NlyoBW0eiS#i2bN3DipjxDvTh1i0dxb3"
					+ "W5ZTemIEIIMNE3penTQ4zmpMkP4jzYJZeSuZOMOgcEckeew4rvPTn9yp1c$#RZtgl$hf31A"
					+ "Zsgiy1Eqlufy4PyxrKQyApTWbT7V9CkkIUl98UUI9zCY1ZyX3yTkUH34s$amyoilajT15PL"
					+ "VmrwtNhEIbClrHyA4$OlsEwZSEI3Vabtx9a$PAPxavbBJ#oahaiE8Oq7QjZafuuvkY9OuwU"
					+ "E2OPQPeXnumzLJoQEvyAC#O=");

	// suppress parser error reporting and let the custom error recovery mechanism handle it
	private static class SDocEvents extends Events
	{
		public void scannerError(Scanner.Exception e)
		{
		}

		public void syntaxError(Symbol token)
		{
		}

		public void unexpectedTokenRemoved(Symbol token)
		{
		}

		public void missingTokenInserted(Symbol token)
		{
		}

		public void misspelledTokenReplaced(Symbol token)
		{
		}

		public void errorPhraseRemoved(Symbol error)
		{
		}
	}

	/**
	 * parse
	 * 
	 * @param source
	 */
	public ISelectorNode parse(String source) throws java.lang.Exception
	{
		ScopeFlexScanner fScanner = new ScopeFlexScanner();

		fScanner.setSource(source);

		Object result = parse(fScanner);

		if (result instanceof ISelectorNode)
		{
			return (ISelectorNode) result;
		}
		else
		{
			String resultType = (result != null) ? result.getClass().getName() : "null";
			String message = "Expected result of ScopeParser to be of type ISelectorNode but was of type "
					.concat(resultType);

			IdeLog.logError(ScriptingActivator.getDefault(), message);

			return null;
		}
	}

	public ScopeParser()
	{
		super(PARSING_TABLES);

		report = new SDocEvents();
	}

	protected Symbol invokeReduceAction(int rule_num, int offset)
	{
		switch (rule_num)
		{
			case 1: // Scope = PipeExpression.d
			{
				final Symbol d = _symbols[offset + 1];

				return d;
			}
			case 2: // PipeExpression = PipeExpression.p PIPE CommaExpression.c
			{
				final Symbol p = _symbols[offset + 1];
				final Symbol c = _symbols[offset + 3];

				return new OrSelector((ISelectorNode) p.value, (ISelectorNode) c.value, "|");
			}
			case 4: // CommaExpression = CommaExpression.c COMMA NegativeLookaheadExpression.t
			{
				final Symbol c = _symbols[offset + 1];
				final Symbol t = _symbols[offset + 3];

				return new OrSelector((ISelectorNode) c.value, (ISelectorNode) t.value);
			}
			case 6: // NegativeLookaheadExpression = NegativeLookaheadExpression.d1 MINUS DescendantExpression.d2
			{
				final Symbol d1 = _symbols[offset + 1];
				final Symbol d2 = _symbols[offset + 3];

				return new NegativeLookaheadSelector((ISelectorNode) d1.value, (ISelectorNode) d2.value);
			}
			case 8: // DescendantExpression = DescendantExpression.a IntersectionExpression.i
			{
				final Symbol a = _symbols[offset + 1];
				final Symbol i = _symbols[offset + 2];

				return new DescendantSelector((ISelectorNode) a.value, (ISelectorNode) i.value);
			}
			case 10: // IntersectionExpression = IntersectionExpression.i AMPERSAND Term.p
			{
				final Symbol i = _symbols[offset + 1];
				final Symbol p = _symbols[offset + 3];

				return new IntersectionSelector((ISelectorNode) i.value, (ISelectorNode) p.value);
			}
			case 12: // Term = IDENTIFIER.i
			{
				final Symbol _symbol_i = _symbols[offset + 1];
				final String i = (String) _symbol_i.value;

				return new NameSelector(i);
			}
			case 13: // Term = LPAREN PipeExpression.a RPAREN
			{
				final Symbol a = _symbols[offset + 2];

				return new GroupSelector((ISelectorNode) a.value);
			}
			case 0: // Grammar = Scope
			case 3: // PipeExpression = CommaExpression
			case 5: // CommaExpression = NegativeLookaheadExpression
			case 7: // NegativeLookaheadExpression = DescendantExpression
			case 9: // DescendantExpression = IntersectionExpression
			case 11: // IntersectionExpression = Term
			{
				return _symbols[offset + 1];
			}
			default:
				throw new IllegalArgumentException("unknown production #" + rule_num);
		}
	}
}
